Jump to content

Blogger

Blog Bot
  • Joined

  • Last visited

    Never
  1. by: Daniel Schwarz Thu, 05 Jun 2025 13:45:56 +0000 In many countries, web accessibility is a human right and the law, and there can be heavy fines for non-compliance. Naturally, this means that text and icons and such must have optimal color contrast in accordance with the benchmarks set by the Web Content Accessibility Guidelines (WCAG). Now, there are quite a few color contrast checkers out there (Figma even has one built-in now), but the upcoming contrast-color() function doesn’t check color contrast, it outright resolves to either black or white (whichever one contrasts the most with your chosen color). Right off the bat, you should know that we’ve sorta looked at this feature before. Back then, however, it was called color-contrast() instead of contrast-color() and had a much more convoluted way of going about things. It was only released in Safari Technology Preview 122 back in 2021, and that’s still the case at the time I’m writing this (now at version 220). You’d use it like this: button { --background-color: darkblue; background-color: var(--background-color); color: contrast-color(var(--background-color)); } CodePen Embed Fallback Here, contrast-color() has determined that white contrasts with darkblue better than black does, which is why contrast-color() resolves to white. Pretty simple, really, but there are a few shortcomings, which includes a lack of browser support (again, it’s only in Safari Technology Preview at the moment). We can use contrast-color() conditionally, though: @supports (color: contrast-color(red)) { /* contrast-color() supported */ } @supports not (color: contrast-color(red)) { /* contrast-color() not supported */ } The shortcomings of contrast-color() First, let me just say that improvements are already being considered, so here I’ll explain the shortcomings as well as any improvements that I’ve heard about. Undoubtedly, the number one shortcoming is that contrast-color() only resolves to either black or white. If you don’t want black or white, well… that sucks. However, the draft spec itself alludes to more control over the resolved color in the future. But there’s one other thing that’s surprisingly easy to overlook. What happens when neither black nor white is actually accessible against the chosen color? That’s right, it’s possible for contrast-color() to just… not provide a contrasting color. Ideally, I think we’d want contrast-color() to resolve to the closest accessible variant of a preferred color. Until then, contrast-color() isn’t really usable. Another shortcoming of contrast-color() is that it only accepts arguments of the <color> data type, so it’s just not going to work with images or anything like that. I did, however, manage to make it “work” with a gradient (basically, two instances of contrast-color() for two color stops/one linear gradient): CodePen Embed Fallback <button> <span>A button</span> </button> button { background: linear-gradient(to right, red, blue); span { background: linear-gradient(to right, contrast-color(red), contrast-color(blue)); color: transparent; background-clip: text; } } The reason this looks so horrid is that, as mentioned before, contrast-color() only resolves to black or white, so in the middle of the gradient we essentially have 50% grey on purple. This problem would also get solved by contrast-color() resolving to a wider spectrum of colors. But what about the font size? As you might know already, the criteria for color contrast depends on the font size, so how does that work? Well, at the moment it doesn’t, but I think it’s safe to assume that it’ll eventually take the font-size into account when determining the resolved color. Which brings us to APCA. APCA (Accessible Perceptual Contrast Algorithm) is a new algorithm for measuring color contrast reliably. Andrew Somers, creator of APCA, conducted studies (alongside many other independent studies) and learned that 23% of WCAG 2 “Fails” are actually accessible. In addition, an insane 47% of “Passes” are inaccessible. Not only should APCA do a better job, but the APCA Readability Criterion (ARC) is far more nuanced, taking into account a much wider spectrum of font sizes and weights (hooray for me, as I’m very partial to 600 as a standard font weight). While the criterion is expectedly complex and unnecessarily confusing, the APCA Contrast Calculator does a decent-enough job of explaining how it all works visually, for now. contrast-color() doesn’t use APCA, but the draft spec does allude to offering more algorithms in the future. This wording is odd as it suggests that we’ll be able to choose between the APCA and WCAG algorithms. Then again, we have to remember that the laws of some countries will require WCAG 2 compliance while others require WCAG 3 compliance (when it becomes a standard). That’s right, we’re a long way off of APCA becoming a part of WCAG 3, let alone contrast-color(). In fact, it might not even be a part of it initially (or at all), and there are many more hurdles after that, but hopefully this sheds some light on the whole thing. For now, contrast-color() is using WCAG 2 only. Using contrast-color() Here’s a simple example (the same one from earlier) of a darkblue-colored button with accessibly-colored text chosen by contrast-color(). I’ve put this darkblue color into a CSS variable so that we can define it once but reference it as many times as is necessary (which is just twice for now). button { --background-color: darkblue; background-color: var(--background-color); /* Resolves to white */ color: contrast-color(var(--background-color)); } And the same thing but with lightblue: button { --background-color: lightblue; background-color: var(--background-color); /* Resolves to black */ color: contrast-color(var(--background-color)); } First of all, we can absolutely switch this up and use contrast-color() on the background-color property instead (or in-place of any <color>, in fact, like on a border): button { --color: darkblue; color: var(--color); /* Resolves to white */ background-color: contrast-color(var(--color)); } Any valid <color> will work (named, HEX, RGB, HSL, HWB, etc.): button { /* HSL this time */ --background-color: hsl(0 0% 0%); background-color: var(--background-color); /* Resolves to white */ color: contrast-color(var(--background-color)); } Need to change the base color on the fly (e.g., on hover)? Easy: button { --background-color: hsl(0 0% 0%); background-color: var(--background-color); /* Starts off white, becomes black on hover */ color: contrast-color(var(--background-color)); &:hover { /* 50% lighter */ --background-color: hsl(0 0% 50%); } } CodePen Embed Fallback Similarly, we could use contrast-color() with the light-dark() function to ensure accessible color contrast across light and dark modes: :root { /* Dark mode if checked */ &:has(input[type="checkbox"]:checked) { color-scheme: dark; } /* Light mode if not checked */ &:not(:has(input[type="checkbox"]:checked)) { color-scheme: light; } body { /* Different background for each mode */ background: light-dark(hsl(0 0% 50%), hsl(0 0% 0%)); /* Different contrasted color for each mode */ color: light-dark(contrast-color(hsl(0 0% 50%)), contrast-color(hsl(0 0% 0%)); } } CodePen Embed Fallback The interesting thing about APCA is that it accounts for the discrepancies between light mode and dark mode contrast, whereas the current WCAG algorithm often evaluates dark mode contrast inaccurately. This one nuance of many is why we need not only a new color contrast algorithm but also the contrast-color() CSS function to handle all of these nuances (font size, font weight, etc.) for us. This doesn’t mean that contrast-color() has to ensure accessibility at the expense of our “designed” colors, though. Instead, we can use contrast-color() within the prefers-contrast: more media query only: button { --background-color: hsl(270 100% 50%); background-color: var(--background-color); /* Almost white (WCAG AA: Fail) */ color: hsl(270 100% 90%); @media (prefers-contrast: more) { /* Resolves to white (WCAG AA: Pass) */ color: contrast-color(var(--background-color)); } } Personally, I’m not keen on prefers-contrast: more as a progressive enhancement. Great color contrast benefits everyone, and besides, we can’t be sure that those who need more contrast are actually set up for it. Perhaps they’re using a brand new computer, or they just don’t know how to customize accessibility settings. Closing thoughts So, contrast-color() obviously isn’t useful in its current form as it only resolves to black or white, which might not be accessible. However, if it were improved to resolve to a wider spectrum of colors, that’d be awesome. Even better, if it were to upgrade colors to a certain standard (e.g., WCAG AA) if they don’t already meet it, but let them be if they do. Sort of like a failsafe approach? This means that web browsers would have to take the font size, font weight, element, and so on into account. To throw another option out there, there’s also the approach that Windows takes for its High Contrast Mode. This mode triggers web browsers to overwrite colors using the forced-colors: active media query, which we can also use to make further customizations. However, this effect is quite extreme (even though we can opt out of it using the forced-colors-adjust CSS property and use our own colors instead) and macOS’s version of the feature doesn’t extend to the web. I think that forced colors is an incredible idea as long as users can set their contrast preferences when they set up their computer or browser (the browser would be more enforceable), and there are a wider range of contrast options. And then if you, as a designer or developer, don’t like the enforced colors, then you have the option to meet accessibility standards so that they don’t get enforced. In my opinion, this approach is the most user-friendly and the most developer-friendly (assuming that you care about accessibility). For complete flexibility, there could be a CSS property for opting out, or something. Just color contrast by default, but you can keep the colors you’ve chosen as long as they’re accessible. What do you think? Is contrast-color() the right approach, or should the user agent bear some or all of the responsibility? Or perhaps you’re happy for color contrast to be considered manually? Exploring the CSS contrast-color() Function… a Second Time originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  2. by: Juan Diego Rodríguez Thu, 05 Jun 2025 11:13:00 +0000 The State of CSS 2025 Survey dropped a few days ago, and besides waiting for the results, it’s exciting to see a lot of the new things shipped to CSS over the past year reflected in the questions. To be specific, the next survey covers the following features: calc-size() shape() Scroll-driven animations Container scroll-state queries CSS Carousels text-box-edge and text-box-trim field-sizing ::target-text @function display: contents Advanced attr() if() sibling-index() and sibling-count() Again, a lot! However, I think the most important questions (regarding CSS) are asked at the end of each section. I am talking about the “What are your top CSS pain points related to ______?” questions. These sections are optional, but help user agents and the CSS Working Group know what they should focus on next. By nature of comments, those respondents with strong opinions are most likely to fill them in, skewing data towards issues that maybe the majority doesn’t have. So, even if you don’t have a hard-set view on a CSS pain point, I encourage you to fill them — even with your mild annoyances. The State of CSS 2025 Survey is out! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  3. by: Abhishek Prakash Thu, 05 Jun 2025 04:30:10 GMT There is some interesting news from this month's desktop Linux market share update. Linux has reached an all-time high market share of 2.69% in the latest Steam Survey. Also, CachyOS has found itself a spot in Linux-specific desktop market share in Steam Survey. 💬 Let's see what else you get in this edition Ubuntu keyboard shortcuts.The World Bank open sourcing a tool.Swiss privacy debacle.Obsidian plugins suggestion.And other Linux news, tips, and, of course, memes!This edition of FOSS Weekly is supported by ANY.RUN.🌟 OtterCookie: New Malware from North Korea Targets Tech and Finance ProfessionalsLazarus Group is currently distributing a stealer malware in fake job offer attacks. Here's how it goes: Lure via LinkedIn: Attackers offer freelance work to fix a minor DApp bug.Triggered Failure: An intentional app error fetches and executes malicious code from external APIMalware Execution: OtterCookie infects the system, stealing victims' browser data and crypto wallets.Read detailed analysis on ANY.RUN's blog. OtterCookie: Analysis of New Lazarus Group MalwareExplore in-depth technical analysis of OtterCookie, a new North Korean Lazarus APT malware that steals victims’ crypto and credentials.ANY.RUN's Cybersecurity BlogMauro Eldritch📰 Linux and Open Source NewsThe World Bank has open sourced Metadata Editor.KDE is getting its own GNOME Boxes counterpart.Ubuntu is adopting the monthly snapshots approach.Organic Maps has been forked over governance concerns.PeerTube is raising funds for further development of its mobile app./e/OS 3.0 has debuted with refined parental controls and new privacy tools.A recent kernel drama sees Linus Torvalds catch a string of suspicious pull requests.Arch Linux is working on a way to handle sponsorships. Sponsorships Seem to Be Coming to Arch Linux!A proposal looks to introduce a transparent sponsorship process to Arch Linux.It's FOSS NewsSourav Rudra🧠 What We’re Thinking AboutSwitzerland is going down a very dystopian path. I hope the law doesn't pass. No More Safe Haven for Privacy? Switzerland Drifts Toward a Surveillance State Due to New Controversial LawsProposed privacy law changes, if passed in parliament, threaten Switzerland’s reputation as a privacy haven.It's FOSS NewsGourav Patnaik🧮 Linux Tips, Tutorials and MoreYou can easily run JavaScript in VS Code.Here are 13 tips and tweaks to get more out of Konsole.Tweaks to get more out of Nautilus file manager.Plugins to enhance your Obsidian knowledge base.If you are up for an experiment, then you could try running macOS on Linux.I Installed macOS on Linux in a VM (for fun sake)Installing macOS as a virtual machine in a Linux system? Well, let’s do it for the sake of some ‘virtual fun’It's FOSSPranav Krishna Desktop Linux is mostly neglected by the industry but loved by the community. For the past 12 years, It's FOSS has been helping people use Linux on their personal computers. And we are now facing the existential threat from AI models stealing our content. If you like what we do and would love to support our work, please become It's FOSS Plus member. It costs $24 a year (less than the cost of a burger meal each month) and you get an ad-free reading experience with the satisfaction of helping the desktop Linux community. Join It's FOSS Plus 👷 Homelab and Maker's CornerLooks like a cyberdeck. Works like a classroom. The CrowPi 3 surprised me with its versatility. CrowPi 3: An All-in-one AI Learning Kit With Cyberdeck FeelA Swiss Army knife for coding education as this kit transforms the programming concepts into tangible experiences. Learn from more than a hundred interactive projects.It's FOSSAbhishek Prakash✨ Project HighlightMarkdown meets the power of LaTeX in this modern typesetting system with Quarkdown. GitHub - iamgio/quarkdown: 🪐 Markdown with superpowers — from ideas to presentations, articles and books.🪐 Markdown with superpowers — from ideas to presentations, articles and books. - iamgio/quarkdownGitHubiamgioHelwan Linux is a distro out of Egypt that feels quite nice. Helwan Linux: A Made-in-Egypt Linux DistributionCheck out what this distro out of Egypt has to offer.It's FOSS NewsGourav Patnaik📽️ Videos I am Creating for YouEssential Ubuntu keyboard shortcuts in action in this week's video. Subscribe to It's FOSS YouTube Channel🧩 Quiz TimeThis time, we have a puzzle for deciphering scrambled application names. Decipher The Scrambled WordsCan you guess the scrambled words? Give it a try!It's FOSSAnkush Das💡 Quick Handy TipIn VirtualBox, you can send keyboard shortcuts like CTRL+ALT+DEL to logout, and a bunch of other keyboard shortcuts to the guest (the virtual machine), without affecting the host (your computer). To send CTRL+ALT+DEL, use Host+Delete. The Host key is usually the Right CTRL key on a keyboard. In the top menu, go to Input ⇾ Keyboard → Keyboard Settings to view and customize additional keyboard shortcuts for interacting with the virtual machine. If you need more input options, you can use the Input ⇾ Keyboard → Soft Keyboard menu to open a virtual keyboard for the guest VM. 🤣 Meme of the WeekLinux users, together, strong! 🤜🤛 🗓️ Tech TriviaBefore Spotify or iTunes, there was Napster. Launched on June 1, 1999, by 18-year-old Shawn Fanning, who built it in his college dorm room, Napster quickly attracted over 20 million users (and viruses). 🧑‍🤝‍🧑 FOSSverse CornerOne of our regular FOSSers, Laura, is looking to compare notes on building Linux and open source software from source. Building Linux and FLOSS programs from source codeStarting a thread on discussion of building parts of Linux, LFS and various packages from source code. This is a spot to compare notes on building from source. We can also discuss pros and cons of various packages/projects to figure out which might be most useful to build from source and which might have less dependencies.It's FOSS CommunityLaura_Michaels❤️ With lovePlease share it with your Linux-using friends and encourage them to subscribe (hint: it's here). Share the articles in Linux Subreddits and community forums. Follow us on Google News and stay updated in your News feed. Opt for It's FOSS Plus membership and support us 🙏 Enjoy FOSS 😄
  4. Blogger posted a blog entry in Linux Tips
    by: Abhishek Prakash Wed, 04 Jun 2025 20:37:04 +0530 This tool lets you generate the SSH config entries quickly. Fill the fields and hit the generate button and copy the entries to your SSH config file. /* Catppuccin Mocha Color Palette */ :root { --ctp-base: #1e1e2e; --ctp-mantle: #181825; --ctp-surface0: #313244; --ctp-surface1: #45475a; --ctp-surface2: #585b70; --ctp-overlay0: #6c7086; --ctp-overlay1: #7f849c; --ctp-text: #cdd6f4; --ctp-subtext1: #bac2de; --ctp-subtext0: #a6adc8; --ctp-blue: #89b4fa; --ctp-lavender: #b4befe; --ctp-mauve: #cba6f7; --ctp-red: #f38ba8; --ctp-green: #a6e3a1; --ctp-yellow: #f9e2af; } * { margin: 0; padding: 0; box-sizing: border-box; } .ssh-config-widget { background: var(--ctp-base); color: var(--ctp-text); font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; border-radius: 12px; border: 1px solid var(--ctp-surface1); max-width: 600px; width: 100%; padding: 24px; margin: 0 auto; } .widget-header { margin-bottom: 24px; } .widget-header h2 { font-size: 1.25rem; font-weight: 600; color: var(--ctp-lavender); margin-bottom: 4px; } .widget-header p { font-size: 0.875rem; color: var(--ctp-subtext0); } .form-group { margin-bottom: 16px; } .form-group label { display: block; font-size: 0.875rem; font-weight: 500; color: var(--ctp-text); margin-bottom: 6px; } .required { color: var(--ctp-red); } .form-group input { width: 100%; padding: 10px 12px; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface1); border-radius: 8px; color: var(--ctp-text); font-size: 0.875rem; transition: all 0.2s ease; } .form-group input:focus { outline: none; border-color: var(--ctp-blue); box-shadow: 0 0 0 2px rgba(137, 180, 250, 0.2); } .form-group input::placeholder { color: var(--ctp-overlay0); } .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } .help-text { font-size: 0.75rem; color: var(--ctp-subtext0); margin-top: 4px; } .error-message { color: var(--ctp-red); font-size: 0.75rem; margin-top: 4px; display: none; } .error-message.show { display: block; } .form-group input.error { border-color: var(--ctp-red); box-shadow: 0 0 0 2px rgba(243, 139, 168, 0.2); } .advanced-section { margin-top: 20px; border: 1px solid var(--ctp-surface1); border-radius: 8px; overflow: hidden; } .advanced-toggle { background: var(--ctp-surface0); padding: 12px 16px; cursor: pointer; display: flex; align-items: center; gap: 8px; font-size: 0.875rem; font-weight: 500; color: var(--ctp-text); transition: background 0.2s ease; user-select: none; } .advanced-toggle:hover { background: var(--ctp-surface1); } .toggle-icon { font-size: 0.75rem; transition: transform 0.2s ease; color: var(--ctp-overlay1); } .toggle-icon.expanded { transform: rotate(90deg); } .advanced-content { padding: 20px; background: var(--ctp-mantle); border-top: 1px solid var(--ctp-surface1); } .checkbox-group { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 12px; } .checkbox-item { display: flex; align-items: center; gap: 8px; } .checkbox-item input[type="checkbox"] { width: 16px; height: 16px; background: var(--ctp-surface0); border: 1px solid var(--ctp-surface2); border-radius: 4px; accent-color: var(--ctp-blue); } .checkbox-item label { font-size: 0.875rem; color: var(--ctp-text); cursor: pointer; margin: 0; } .generate-btn { width: 100%; background: var(--ctp-blue); color: var(--ctp-base); border: none; padding: 12px 16px; font-size: 0.875rem; font-weight: 600; border-radius: 8px; cursor: pointer; transition: all 0.2s ease; margin-top: 24px; } .generate-btn:hover { background: var(--ctp-lavender); } .generate-btn:active { transform: translateY(1px); } .output-section { margin-top: 24px; border: 1px solid var(--ctp-surface1); border-radius: 8px; overflow: hidden; } .output-header { background: var(--ctp-surface0); padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--ctp-surface1); } .output-header h3 { font-size: 0.875rem; font-weight: 600; color: var(--ctp-text); } .copy-btn { background: var(--ctp-green); color: var(--ctp-base); border: none; padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 0.75rem; font-weight: 500; transition: background 0.2s ease; } .copy-btn:hover { background: var(--ctp-yellow); } .copy-btn.copied { background: var(--ctp-mauve); } .config-output { background: var(--ctp-mantle); color: var(--ctp-text); padding: 16px; font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; font-size: 0.8rem; line-height: 1.5; white-space: pre-wrap; overflow-x: auto; } .output-footer { padding: 12px 16px; background: var(--ctp-surface0); font-size: 0.75rem; color: var(--ctp-subtext0); } .output-footer code { background: var(--ctp-surface1); padding: 2px 6px; border-radius: 4px; font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace; color: var(--ctp-blue); } @media (max-width: 640px) { .form-row { grid-template-columns: 1fr; } .checkbox-group { grid-template-columns: 1fr; } } Generate SSH config file entries Generate valid ~/.ssh/config entries Host Alias * Connection nickname Hostname/IP * Server address Username Leave empty for current user Port Default: 22 (use 1-65535) Identity File If you have multiple keys ▶ Advanced Options Proxy Jump Host Jump through this host first Local Forward local:remote:port Remote Forward remote:local:port Additional Options Forward X11 Forward SSH Agent Strict Host Key Checking Keep Alive Generate Config Generated Config Copy Add to ~/.ssh/config then connect with: ssh myserver With the ~/.ssh/config file, you can save the details about various servers you regularly connect to via SSH. It generates one set of entries for a server at a time. If you have multiple servers, you need to manually add the generated entries one after another in ~/.ssh/config file. Learn more about using SSH config file in detail. How to Use SSH Config File [Beginner’s Guide]Using SSH profiles can help you in cases where you regularly connect to various servers. No need to remember the IP address and other such details for SSH connection.Linux HandbookAbhishek Prakash
  5. by: Sreenath Wed, 04 Jun 2025 12:59:54 GMT In an earlier article, I wrote about using plugins in Obsidian. In this one, let me share a few of my favorite plugins. I recommend them but only use the ones that fit your needs. Just to recall, Obsidian has two kinds of plugins: Core plugins: Officially developed and maintained by the Obsidian team.Community Plugins: Created by users in the Obsidian community🚧Note that some plugins may make your Markdown notes fully readable only in Obsidian as they add extra features that are not available in usual Markdown. This can be a vendor lock in. Use plugins only according to your needs.Essential Core PluginsAt the time of writing this article, I see 28 core plugins in my Obsidian installation. I have picked only a handful of them. It doesn't mean others are not good. All core plugins have some use case for a particular set of users! Several of the plugins I discuss here are enabled by default. But these plugins have settings of their own and I share these settings that have enhanced my note management experience in Obsidian. ✋Non-FOSS Warning! Obsidian is not an open source software but it is loved and used by many open source developers and Linux users.BacklinksThe backlinks are among Obsidian's greatest features. It is crucial for managing interconnected notes and data. I know that the backlink plugin is enabled by default but there is a useful feature that you'll have to manually enable. It is “Show backlinks at the bottom of notes” option. Enable it by going to Backlinks plugin settings. Enable backlinksNow, under each note, backlinks will be shown. 0:00 /0:18 1× Backlinks in Obsidian It is particularly useful if you are creating new notes from a single place like Daily Notes, which is our next plugin! Daily NotesDaily Notes is like diary pages. It will create a Markdown page for each day and you can write your thoughts here. By default, you can access the daily notes from the Obsidian ribbon menu. But a more efficient way is to open daily notes whenever you open Obsidian. Go to the Daily Notes settings. Here, enable the "Open daily note on startup" toggle button. Daily Notes SettingsIn the screenshot above, you can see some other settings have been changed. Date Format: How the title of the daily note appear. You can get the date format options here.New file location: I have created a separate folder called Journals in my Obsidian vault to store all the daily notes.Page PreviewThis is enabled by default for you. With this plugin, you can hover over a note while pressing the CTRL key to get a preview. You can also quickly edit the note in the preview or go to another sub-preview, etc. Very useful tool if you are deep into note interlinking. 0:00 /0:23 1× Preview page in Obsidian Slash CommandsThis plugin is disabled by default. Go to the Core Plugins in Obsidian settings and enable this plugin. Once enabled, you can press the / key when typing a note to access commands. For example, insert attachment, insert code block, etc. A simple preview is shown in the below video. 0:00 /0:24 1× Slash command in Obsidian Notion, Ghost and many modern editors use this feature.| Web ViewerThis is a cool plugin that allows you to visit web links from within Obsidian. More than that, you can save a website to vault using this core plugin. It is not enabled by default, so do that first. Once enabled, click on the settings gear adjacent to the plugin to go to the plugin settings. Web viewer settings buttonHere, you can set further options like where to save the page by default, search engine, etc. Web Viewer SettingsYou can see some examples in the video below. Web viewer in Obsidian Interesting community plugins I likeNow, let's take a look at some cool community plugins that can enhance your knowledge base, as they do for me. CalendarIf you are a daily notes writer, this is a must-have plugin. Even if you are not into diary writing, it is still pretty cool to have a calendar placed on Obsidian. Calendar ViewYou can visit notes of any date simply by clicking on that date. If there is no note, it will prompt you to create one! There are many more features that you can explore, like a meter to track how much you have written on a particular day. 💡If you press CTRL key and hover over a date, those day's notes will be shown in a preview.Calendar PluginQuickAddQuickAdd is a much needed automation tool in Obsidian. It offers features like templates, captures, macros, multis, etc. which essentially allow users to create notes quickly. For example, the template feature can create a note based on a given template in a specified directory. All you have to do is invoke the command. The screenshot below shows three templates created by me for my use cases. Created TemplatesUse the settings gear to change additional settings like where to create a note, open the note automatically, etc. The video below shows how it quickly creates a note on a specified location. 0:00 /0:13 1× QuickAdd Working With macros, you can even assign key bindings to make your workflow even faster! QuickAddIconizeEmojis and icons are all the rage these days. From GitHub to changelogs, you'll see them everywhere. How about adding them to Obsidian? Obsidian organizes notes into folders and subfolders. With the Iconize plugin, you can set icons to folders. Icons applied to foldersYou can add new icon packs by going to the Settings → Community plugins → Installed plugins -→Iconize -→Settings gear → Icon packs. Icon packs added in IconizeRight-click on a folder or file and use the Change icon option to add a new icon to that folder/file. IconizeHighlightrRemember highlighting important stuff in a book? You can do the same in your notes on Obsidian. Highlight text in Vimeo It also provides different styles of highlighting, all selectable from the plugin settings. HighlightrCallout Manager and Callout SuggestionsThese are two different plugins which, when used together, are a great way to add callouts. 📋If you are not aware, callout blocks can improve your notes by making specific visually separated blocks for tips, warnings, etc. Like this 'note' callout block I used for telling you about callouts.By default, obsidian has some callouts like Note, Tips, Warnings, etc. Callout Manager allows you to create more callout blocks. Say you want to create a new callout block called "Read Later" and assign a particular color and icon. You can do that with this plugin. Callout blocks from Callout ManagerThe Callout Suggestions plugins will help you access these defined callout blocks easily in your notes. You can press >! and a dropdown menu will appear asking what block to use. 0:00 /0:23 1× Inserting Callouts in Obsidian PDF++Annotating a PDF document is a must-have feature in any PDF viewer. How about doing it in Obsidian? PDF++ is a great tool for this purpose. You can add your PDF notes to your vault and start annotating! Once the plugin is installed and enabled, make sure you have enabled the PDF editing feature. PDF++ plugin settingsNow, you can select text and then right-click to get the annotation menu. Unlike other plugins, this has a slight learning curve and plenty of options to tweak. Use it carefully. Annotate PDF in ObsidianPDF++LanguageTool IntegrationThis is for those who want to create notes without grammatical errors or spelling mistakes. LanguageTool is a proofreading software that checks the grammar, style, and spelling in over 20 languages. With this plugin, you can get error notifications for your text in Obsidian. If you have a premium subscription for LanguageTool, you can use it here as well. Spell check in Obsidian🚧You should disable the Obsidian spell check (Settings → Editor → Behavior → Spell Check) feature if you want to use this plugin.LanguageTool IntegrationTasksYou can use Obsidian as a task/to-do manager. That's no secret. However, Tasks is plugin that can do a lot more than just simple to-dos. It supports scheduling tasks, recurring tasks etc. You can also list all the tasks, today's tasks, etc. by using simple tasks specific queries. To create a task, you can enter CTRL+P (open command in Obsidian) and search for Tasks. Using the Tasks plugin to create tasksYou can retrieve tasks as shown in the small video below: 0:00 /0:28 1× Retrieve tasks in Obsidian TasksExcalidrawExcalidraw is a plugin to edit and view Excalidraw drawings in Obsidian. This sketching solution can make wonderful diagrams within Obsidian, embed drawings into your documents and much more. An Excalidraw drawing in ObsidianYou can find a huge list of settings for this plugin in the Obsidian settings. If you are into creative note-taking, look no further. ExcalidrawHonorable mentionsStyle Settings: Allows you to tweak several themes in Obsidian. One such theme that I am using and is heavily customizable is Border.Git: Allows you to version control your notes. You can pull changes from and push changes to GitHub, GitLab, etc.Dataview: Dataview is a live index and query engine over your personal knowledge base. You can query data from your Obsidian vault.QuickAdd: QuickAdd is like a super-smart shortcut button in Obsidian that lets you quickly create new notes or add stuff to existing ones using pre-made templates and automated steps you set up.Kanban: This plugins created a Markdown-based Kanban board.There are many other plugins, enabled/disabled in a default Obsidian installation. What I mentioned above are a couple of special ones. Don't forget to read the descriptions and try others too. Now I let you share your favorite Obsidian plugin in the comments.
  6. Blogger posted a blog entry in Linux Tips
    by: Abhishek Prakash Wed, 04 Jun 2025 12:11:12 +0530 I hope I am not committing blasphemy but you can use the mouse in Vim. Press Esc to go to command mode in Vim and use: :set mouse=a It will enable mouse mode immediately in all Vim modes, i.e. normal, insert and visual. To disable the mouse mode, use this: :set mouse=If you want to use mouse mode all the time, I am not judging you, add this entry to your ~/.vimrc file: set mouse=aSave, restart Vim, and your mouse now works for clicking, scrolling, and selecting text. What does mouse mode do in Vim?First thing first, the mouse mode has limited usage in Vim. Don't expect to get a notepad like experience just because you enabled mouse mode. It does add some functionality and ease of use like: Jump to exact locations without counting lines or using searchWheel scrolling while dealing with long filesEasy text selection: double click to select a word, triple click to select an entire line, use mouse click and drag for the desired text selectionClick between panes and resize them easily while using split windows in VimWhile using tabs, click on other tabs to switch, click on X (should be visible at top right in mouse mode) to close a tab, double click on tab bar to create new empty files in new tabsUse middle click to paste from system clipboardThe video below shows some of the above discussed featured in action: 0:00 /0:21 1× Vim Mouse Mode demonstration Mouse mode doesn't replace Vim's keyboard efficiency - it complements it. Think of it as having both a sports car's manual controls and cruise control available. 📋Mouse mode behavior varies by terminal and some terminal emulators may require specific settings. If you are using tmux, ensure both Vim and tmux have mouse mode enabled for proper interaction.Understanding mouse mode OptionsVim's mouse configuration works like a permission system: set mouse=a " All modes (normal, visual, insert, command) set mouse=n " Normal mode only set mouse=v " Visual mode only set mouse=i " Insert mode only set mouse=c " Command mode only set mouse=nv " Normal and visual modesMostly, you would want mouse=a - which is like having universal access rather than mode-specific restrictions. 💡You can refer to Vim's official mouse documentation: :help mouse-usingConclusionI am not a Vim purist and I won't judge you if you use mouse in Vim, which is known for its keyboard-centric approach to productivity. Mouse mode doesn't diminish Vim's keyboard efficiency - it provides additional options for specific scenarios. If you feel too uncomfortable with Vim at the beginning, opt for the hybrid approach where you use mouse for navigation and positioning, keyboard for editing operations. I welcome your comments.
  7. by: Adnan Shabbir Wed, 04 Jun 2025 04:44:46 +0000 Windows Subsystem for Linux (WSL) allows you to run Linux distros within the Windows operating system. WSL is available in multiple versions: WSL1 (older but still supported) and WSL2 (newer with continuous development support). Recently, on May 19, 2025, Microsoft conducted a 2025 Build Conference where they announced the open-source nature of WSL for Windows, which is huge news for Linux users and the open-source community. In today’s guide, I will elaborate on the recent development in the WSL project, the open-source nature of the WSL, how mature its open-source nature is, and Microsoft’s journey towards open-source. So, let’s get started: Windows Subsystem for Linux (WSL) is now Open Source Road to Open Source WSL How can I Contribute to Open-Source WSL? Basic Understanding of the WSL Architecture Bonus: Keep Your WSL Updated Conclusion Windows Subsystem for Linux (WSL) is now Open Source Yes, you heard that right, Microsoft has recently declared WSL as an open-source component of Windows. Microsoft has officially released the source code of WSL on May 19, 2025, at the Microsoft Build 2025 Conference. As per the announcement of Microsoft, the WSL is completely open-sourced except for the following three components: “Lxcore.sys”: Kernel-side driver that powers WSL1, i.e., component that translates Linux commands for Windows in WSL1. “P9rdr.sys” and “p9n9.dll”: These 9P protocol components refer to the filesystem redirection from Windows to Linux. The above three components are tightly integrated with Windows core processes. For instance, the “Lxcore.sys” has to interact with the Windows kernel. Similarly, the 9P protocol components handle Windows files and directories. These deep integrations of WSL’s components with Windows might be the reasons behind keeping them closed-source. This was about Microsoft’s recent announcement. Now, let me take you through Microsoft’s path towards open-source WSL. Road to Open Source WSL In 2019, Microsoft started maintaining its own Linux Kernel specifically for WSL, and it was declared an open-source component. Since then, the WSL community has started growing and contributing to the WSL project. Later on, the WSLg component became open source, which provides the graphical applications support for the Linux applications in the WSL. Microsoft gradually moved WSL to an open-source project. In 2021, Microsoft separated the Windows code base from the WSL code base. The newly released WSL was then available on the Microsoft Store for Windows 11 users. However, in 2022, it was made available for Windows 10 users too. Apart from that, the development and upgradation of WSL keep going, i.e., the latest available WSL is “2.5.7.0”. How can I Contribute to Open-Source WSL? Microsoft has provided the source code Git Repo of WSL, where you can contribute to reporting the bugs/issues or developing the source code from scratch. A Linux enthusiast may love to look into the source code and contribute according to their interest. If you are facing any technical issues relevant to WSL, you can ask for assistance on WSL’s Git repo. Similarly, if you are a regular user, you must keep on visiting the WSL repo and contribute to any other issues of the users in the comments. Basic Understanding of the WSL Architecture Since two different operating systems are collaborating, the component functionalities would differ in both environments. Let’s have a bird’s eye view of the WSL architecture: Windows Host: The components hosted on the Windows side are the entry points to interact with the WSL. wsl.exe: Command line utility to launch or manage the WSL. wslconfig.exe: This mostly belongs to WSL 1 and is used to configure WSL 1. wslg.exe: Launch and manage the GUI apps from Windows. wslservice.exe: This is the background process, i.e., launch the VM, start/stop the distros attached, mount the filesystem, etc. WSL VM Service: These components work inside the WSL VM and are triggered when the user executes Windows components. init: The initial process that starts in the Linux environment. It initializes the necessary processes and manages the distribution at the WSL end. gns (Networking): Manages DNS and network integration with Windows. localhost (port forwarding): The localhost running inside the Linux VM is the port forwarding. Plan9 Server: The server is responsible for file sharing from Windows to Linux. Bonus: Keep Your WSL Updated When you install WSL from the command line, it might fetch and install a bit lower version. Or even if it is up to date as per your installation, you must check for updates and get the latest available version: Before updating: wsl -v Updating WSL: wsl --update Both the Linux Kernel and WSL versions are updated: wsl -v That’s all from this post. Conclusion On May 19, 2025, Microsoft announced the WSL as an open-source project. Not 100% open-source, yet a major advancement in the open-source world. Microsoft has long been working on this. Microsoft has held three components closed-source because of their deep integration with the Windows core processes. In today’s post, I have talked about the open-source nature of WSL and Microsoft’s path to open-source WSL development. FAQs: Q1: Is WSL completely open source now? Yes, except for only three components, which are “Lxcore.sys”, “P9rdr.sys”, and “p9n9.dll”. Q2: How can I contribute to WSL? Microsoft has provided the source code Git Repo of WSL, where you can contribute to reporting the bugs/issues or developing the source code from scratch. Q3: Is WSL a replacement for Linux? WSL cannot be referred to as a full replacement for Linux. WSL is just a subsystem within Windows. Q4: Can WSL open a GUI? Yes, WSL can open a Linux GUI application with the help of WSLg, i.e., introduced in 2021 for Windows 11 and in 2022 for Windows 10.
  8. by: Andy Clarke Tue, 03 Jun 2025 14:39:04 +0000 Like ’em or loath ’em, whether you’re showing an alert, a message, or a newsletter signup, dialogue boxes draw attention to a particular piece of content without sending someone to a different page. In the past, dialogues relied on a mix of divisions, ARIA, and JavaScript. But the HTML dialog element has made them more accessible and style-able in countless ways. So, how can you take dialogue box design beyond the generic look of frameworks and templates? How can you style them to reflect a brand’s visual identity and help to tell its stories? Here’s how I do it in CSS using ::backdrop, backdrop-filter, and animations. Design by Andy Clarke, Stuff & Nonsense. Mike Worth’s website will launch in June 2025, but you can see examples from this article on CodePen. I mentioned before that Emmy-award-winning game composer Mike Worth hired me to create a highly graphical design. Mike loves ’90s animation, and he challenged me to find ways to incorporate its retro style without making a pastiche. However, I also needed to achieve that retro feel while maintaining accessibility, performance, responsiveness, and semantics. A brief overview of dialog and ::backdrop Let’s run through a quick refresher. Note: While I mostly refer to “dialogue boxes” throughout, the HTML element is spelt dialog. dialog is an HTML element designed for implementing modal and non-modal dialogue boxes in products and website interfaces. It comes with built-in functionality, including closing a box using the keyboard Esc key, focus trapping to keep it inside the box, show and hide methods, and a ::backdrop pseudo-element for styling a box’s overlay. The HTML markup is just what you might expect: <dialog> <h2>Keep me informed</h2> <!-- ... --> <button>Close</button> </dialog> This type of dialogue box is hidden by default, but adding the open attribute makes it visible when the page loads: <dialog open> <h2>Keep me informed</h2> <!-- ... --> <button>Close</button> </dialog> I can’t imagine too many applications for non-modals which are open by default, so ordinarily I need a button which opens a dialogue box: <dialog> <!-- ... --> </dialog> <button>Keep me informed</button> Plus a little bit of JavaScript, which opens the modal: const dialog = document.querySelector("dialog"); const showButton = document.querySelector("dialog + button"); showButton.addEventListener("click", () => { dialog.showModal(); }); Closing a dialogue box also requires JavaScript: const closeButton = document.querySelector("dialog button"); closeButton.addEventListener("click", () => { dialog.close(); }); Unless the box contains a form using method="dialog", which allows it to close automatically on submit without JavaScript: <dialog> <form method="dialog"> <button>Submit</button> </form> </dialog> The dialog element was developed to be accessible out of the box. It traps focus, supports the Esc key, and behaves like a proper modal. But to help screen readers announce dialogue boxes properly, you’ll want to add an aria-labelledby attribute. This tells assistive technology where to find the dialogue box’s title so it can be read aloud when the modal opens. <dialog aria-labelledby="dialog-title"> <h2 id="dialog-title">Keep me informed</h2> <!-- ... --> </dialog> Most tutorials I’ve seen include very little styling for dialog and ::backdrop, which might explain why so many dialogue boxes have little more than border radii and a box-shadow applied. Out-of-the-box dialogue designs I believe that every element in a design — no matter how small or infrequently seen — is an opportunity to present a brand and tell a story about its products or services. I know there are moments during someone’s journey through a design where paying special attention to design can make their experience more memorable. Dialogue boxes are just one of those moments, and Mike Worth’s design offers plenty of opportunities to reflect his brand or connect directly to someone’s place in Mike’s story. That might be by styling a newsletter sign-up dialogue to match the scrolls in his news section. Mike Worth concept design, designed by Andy Clarke, Stuff & Nonsense. Or making the form modal on his error pages look like a comic-book speech balloon. Mike Worth concept design, designed by Andy Clarke, Stuff & Nonsense. dialog in action Mike’s drop-down navigation menu looks like an ancient stone tablet. Mike Worth, designed by Andy Clarke, Stuff & Nonsense. I wanted to extend this look to his dialogue boxes with a three-dimensional tablet and a jungle leaf-filled backdrop. Mike Worth, designed by Andy Clarke, Stuff & Nonsense. This dialog contains a newsletter sign-up form with an email input and a submit button: <dialog> <h2>Keep me informed</h2> <form> <label for="email" data-visibility="hidden">Email address</label> <input type="email" id="email" required> <button>Submit</button> </form> <button>x</button> </dialog> I started by applying dimensions to the dialog and adding the SVG stone tablet background image: dialog { width: 420px; height: 480px; background-color: transparent; background-image: url("dialog.svg"); background-repeat: no-repeat; background-size: contain; } Then, I added the leafy green background image to the dialogue box’s generated backdrop using the ::backdrop pseudo element selector: dialog::backdrop { background-image: url("backdrop.svg"); background-size: cover; } Mike Worth, designed by Andy Clarke, Stuff & Nonsense. I needed to make it clear to anyone filling in Mike’s form that their email address is in a valid format. So I combined :has and :valid CSS pseudo-class selectors to change the color of the submit button from grey to green: dialog:has(input:valid) button { background-color: #7e8943; color: #fff; } I also wanted this interaction to reflect Mike’s fun personality. So, I also changed the dialog background image and applied a rubberband animation to the box when someone inputs a valid email address: dialog:has(input:valid) { background-image: url("dialog-valid.svg"); animation: rubberBand 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; } @keyframes rubberBand { from { transform: scale3d(1, 1, 1); } 30% { transform: scale3d(1.25, 0.75, 1); } 40% { transform: scale3d(0.75, 1.25, 1); } 50% { transform: scale3d(1.15, 0.85, 1); } 65% { transform: scale3d(0.95, 1.05, 1); } 75% { transform: scale3d(1.05, 0.95, 1); } to { transform: scale3d(1, 1, 1); } } Tip: Daniel Eden’s Animate.css library is a fabulous source of “Just-add-water CSS animations” like the rubberband I used for this dialogue box. Changing how an element looks when it contains a valid input is a fabulous way to add interactions that are, at the same time, fun and valuable for the user. Mike Worth, designed by Andy Clarke, Stuff & Nonsense. That combination of :has and :valid selectors can even be extended to the ::backdrop pseudo-class, to change the backdrop’s background image: dialog:has(input:valid)::backdrop { background-image: url("backdrop-valid.svg"); } Try it for yourself: CodePen Embed Fallback Conclusion We often think of dialogue boxes as functional elements, as necessary interruptions, but nothing more. But when you treat them as opportunities for expression, even the smallest parts of a design can help shape a product or website’s personality. The HTML dialog element, with its built-in behaviours and styling potential, opens up opportunities for branding and creative storytelling. There’s no reason a dialogue box can’t be as distinctive as the rest of your design. Andy Clarke Often referred to as one of the pioneers of web design, Andy Clarke has been instrumental in pushing the boundaries of web design and is known for his creative and visually stunning designs. His work has inspired countless designers to explore the full potential of product and website design. Andy’s written several industry-leading books, including ‘Transcending CSS,’ ‘Hardboiled Web Design,’ and ‘Art Direction for the Web.’ He’s also worked with businesses of all sizes and industries to achieve their goals through design. Visit Andy’s studio, Stuff & Nonsense, and check out his Contract Killer, the popular web design contract template trusted by thousands of web designers and developers. Getting Creative With HTML Dialog originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  9. by: Chris Coyier Mon, 02 Jun 2025 17:01:09 +0000 Let’s do typography stuff! Video: “A live demo by me of early font editors on a real Macintosh Plus” by Mark Simonson Font: “Is this font easy for you to read? Good—that’s the idea.” Hyperlegible is the name of the font, designed for people with low vision. Technique: “Fluid typography means thinking in terms of type scales and flexible spacing across your defined design space.” Richard Rutter goes retrofitting a new type sizing technique into an old layout. Miriam is also thinking about all this. Richard also has a good one on avoiding faux bold, which has afflicted me many times. My hot take is that browsers shouldn’t do faux nuthin. Font: “To help young readers of all skill levels, we’re introducing Kermit, a child-friendly typeface created by the type design studio Underware.” It’s fairly pricey but I can imagine it being perfect for some projects. Like Comic Sans but cooler. P.S. you should really try Comic Code on CodePen, it’s awesome. Fonts: “UNCUT.wtf is a free typeface catalogue, focusing on somewhat contemporary type.” A lot of them are super similar which makes me wonder if many of them come from students taking a design class or something. Journey: “One day, I saw what felt like Gorton on a ferry traversing the waters Bay Area. A few weeks later, I spotted it on a sign in a national park. Then on an intercom. On a street lighting access cover. In an elevator. At my dentist’s office. In an alley.” Marcin Wichary on Manhattan’s hardest working typeface. Performance: “… file sizes of web fonts? I personally don’t have a gut feeling how much is too much and how much is to be expected.” Stoyan Stefanov reckons 20k is fair. Behind the Scenes: “This meant that on web we could simply start our font stacks with Verdana, pick a couple of reasonable fallbacks, and get IKEA branding effectively for free.” IKEA didn’t end up using Verdana, but I wish they did, I kinda love it at small sizes. This is a great look at a major typographic choice at a major brand from Robin Whittleton. Technique: “…we added text-wrap: balance on WordPress.org, and quickly got community feedback that it led to awkward, unexpected breaks in Japanese and Korean.” Kelly Choyce-Dwan whips out stuff like word-break: auto-phrase; for the win.
  10. by: Abhishek Prakash Mon, 02 Jun 2025 14:28:22 GMT Most educational programs keep students trapped behind screens, manipulating virtual objects and producing digital outputs. This is why the Raspberry Pi and Arduino like devices provide such a great learning environment. Adding hardware components to the board gives meaning to the software. The CrowPi takes this forward by giving an entire learning laboratory that transforms abstract programming concepts into tangible, interactive experiences. Elecrow has been known for creating great Raspberry Pi products. They are launching their latest product, CrowPi 3. They sent me the device to test and share the experience and that's what I am going to do in this article. What is CrowPi 3?Think of the CrowPi 3 as a Swiss Army knife for coding education - it packs dozens of sensors, programming environments, and learning tools into one portable, briefcase. Instead of juggling separate breadboards, sensors, and computers, everything lives in a single ecosystem. The CrowPi 3 transforms abstract programming concepts into tangible experiences. Write Python code to detect motion → PIR sensor triggers alarm. Code an NFC reader → tap a card to spawn TNT blocks in Minecraft. It's programming with immediate, visible consequences. The core components are: Raspberry Pi 5 as the brain of the kit (advance kit includes the pi)20+ sensors pre-wired and ready4.3" touchscreen + HDMI connections for external monitorsBuilt-in breadboards and GPIO accessArduino and Pi Pico can be attached on top of it128 GB micro SD card with custom operating systemThis custom operating system is a customized version of Raspbian OS and has numerous ready-to-explore projects across multiple programming environments like Python, Scratch etc. A dedicated section of AI projects to try beginner level AI projects using the on-board camera and various sensors. No prizes for guessing that there were at least two more such CrowPi kits in the past and considering the fact that this is the third such inastallment, I would think that the first two devices met with success. Who is this kit for?The primary audience for CrowPi 3 is children aged 8-16 who are learning programming and AI coding fundamentals. Of course, it is not just limited to children. People new to Raspberry Pi/Arduino would also benefit from the guided experiences of such a kit. I also think that it is suitable for teachers that need turnkey STEM curriculum tools. The kit has streamlined learning of all levels with a mix of both software and hardware. Start with drag-drop Scratch blocks, graduate to Python sensor control, eventually tackle more intense AI projects. But all this can be assembled...Sure, you may not need or use all of the sensors provided in the kit. And yes, you can get the sensors and accessories separately and use them with tons of open source projects available online but kits like CrowPi, make it all streamlined. This is ideal for schools and for people who want to explore programming the hardware devices without struggling with the hardware assembly. Hardware assembly could be fun, too, but it could be frustrating and time-consuming. These kits flatten the learning curve a little, letting the students enjoy dipping their toes in the vast ocean of electronic geekery. CrowPi 3 Kit contents📋The kit I received for this review is the basic one. The advanced kit comes with a Raspberry Pi 5 16 GB already fixed in, batteries for extra portability, an additional SD card with retro games on it, game controllers and a few more accessories. The basic kit has the following item in addition to the pre-wired ones on the board already: Power Supply x1Screwdriver x1Stepped Motor x1Infrared Receiver Head x1RFID Card + Tag x1IR Remote Control x1User Manual x1Motor + Fan Blade x1USB A to Micro B Cable x1Type-C to Type-C Cable x1NFC Card x1TF Card Reader x1A Swiss Army knife for coding education as this kit transforms the programming concepts into tangible experiences. Learn from more than a hundred interactive projects.Crowtail-9G Servo x1Components Pack (with wires, LED and more) x1128G TF Card with Customized System x1Accessories in CrowPi 3 Basic kitThe advanced kit has these items in addition to everything in the basic kit: NFC Tag x10Raspberry Pi 5 (16GB) x1Laptop Tote x12.4G Wireless Keyboard + Mouse x132G TF Card with Customized System x1Minecraft paper x5Crowtail - I2C HUB x118650 Lithium Battery x2Game Controller x2Experiencing CrowPi 3The CrowPi kit comes in a briefcase styled box which kind of gives me the cyberdeck feel. The case looks good with the frosted glass. CrowPi 3 Kit with frosted glass coverLet me share my experience using this open source AI education kit. The buildThis is a well-thought and well-built device. It comes in a briefcase styled box with a fold-out handle that makes it easy to carry. The frosted glass cover doesn't come off easily as it has strong magnets and all the sensors and components are firmly fixed in the kit. I didn't do a fall test by dropping it to the ground to check if it can survive something like that. If you ever do this, accidentally or otherwise, do share the data with us 😜 There is an empty slot at the bottom that could hold a few tiny accessories. It's a small thing but Built-in touchscreenThe small screen has touch capability and the touch response is pretty decent but I would only use it when there are no other options available. My fat fingers and eyes are not suitable for tiny screens anymore. Okay, I could access pretty much most of the things with this tiny screen and it becomes even easier to use when I connected proper keyboard and mouse to it. Still, it is tiny which is okay for retro gaming and a few small stuff to check the output or see debug info but you'll need a proper screen to make use of it. This is evident as the customized learning interface is not properly displayed in the tiny screen. CrowPi 3's small screen doesn't properly display its customized learning interfaceRaspbian OS customized for interactive learning📋I still don't have a capture card for Raspberry Pi (a shame, I know) and hence I cannot share good quality images here. Apologies as I order a capture card.The interface, when experienced on a proper monitor, shows the IDE tools and interactive project to choose from. I used their CrowView Notebook for this purpose, although it can be connected to any external monitor. Select interactive project from left or use IDE from the right to code on your ownTo use the interactive projects, you'll have to create an account. I think it's a local user account that stays on your system. This way, more than one people can save their progress. A local user account saves your progress on the deviceIn the image below, you can see that it provides 39 Python projects that teach you the basic Python programming that also interact with various sensors and components on the kit. Interactive Python project interfaceWhen you select a project, you have instructions on half the screen and the code editor or tool in the other half. And the programs you run can also impact the hardware (most of the time) and you can see it on CrowPi 3 kit. For example, in the screenshot above (if it is visible), it creates a simple program that sounds the buzzer on the board for the specified time. See, this allows an easier way of learning with both software and hardware in the mix as you have pre-built scenario with instructions and their impact is visible on the hardware. You are not restricted to this customized interface. You can also use the classic Raspbian interface and access the editors and projects from there as well. The sensory board experienceThe kit features two breadboards positioned strategically on the main board, eliminating the frustrating "where do I connect this?" moments. While breadboards are available for custom circuits, most sensors come pre-connected and ready to use. There are easy sample projects to test the functionality of these sensors and they are fun to experiment even for adults. The cooling fanThe cooling fan is loud and runs continuouslyThere is a visible cooling fan with RGB lighting. While it seemed cool at the beginning, it started to annoy me later. Don't get me wrong. I know that Raspberry Pi like devices must have some sort of cooling system. But this fan is much too loud for its size. And it runs continuously, unnecessarily. There is no on/off button for that and I don't expect such a feature. Now, this could be a good programming challenge to write a script that turns the fan off when the CPU reaches a certain temperature threshold. Bottom lineThe CrowPi 3 solves the "hello world" problem in programming education. Instead of printing text to screens, students control real-world devices and see immediate physical results. I mean, those variables are more meaningful when they represent real sensor readings. The conditional logic makes more sense when you can control lights and motors with it. The ready-to-use kit eliminates the setup frustration that could arise from manually connecting all those sensors, fans and lights. This is suitable for classrooms, as well as motivated self-learning at home. It is also a good Christmas gift candidate if you have children in your family that might be interested in learning AI, coding and electronics. I don't have the pricing at the time of writing this review. Elecrow is planning to run a pre-order campaign through Kickstarter very soon. Please check it for pricing and release dates. CrowPi 3 on Kickstarter
  11. by: Abhishek Prakash Sat, 31 May 2025 20:19:04 +0530 Time to practice your Bash script and develop a simple game. ExerciseCreate a bash script that implements a number guessing game. The script should: Generate a random number between 1 and 100Allow the user to make guessesProvide feedback whether the guess is too high, too low, or correctCount the number of attemptsAllow the user to play again after winningThe game should continue until the user guesses correctly, and then ask if they want to play another round. 💡 HintsUse $RANDOM to generate random numbersThe modulo operator % can help limit the rangeUse a while loop for the main game logicConsider using a nested loop structure for replay functionalityInput validation is important - check if the user enters a valid numberTest dataTest Case 1: Basic game flow $ ./guessing_game.sh Welcome to the Number Guessing Game! I'm thinking of a number between 1 and 100. Enter your guess: 50 Too low! Try again. Enter your guess: 75 Too high! Try again. Enter your guess: 62 Too low! Try again. Enter your guess: 68 Congratulations! You guessed it in 4 attempts! Do you want to play again? (yes/no): no Thanks for playing! Goodbye!Test Case 2: Input validation $ ./guessing_game.sh Welcome to the Number Guessing Game! I'm thinking of a number between 1 and 100. Enter your guess: abc Invalid input! Please enter a number between 1 and 100. Enter your guess: 150 Your guess must be between 1 and 100! Enter your guess: 0 Your guess must be between 1 and 100! Enter your guess: 42 Too high! Try again.Test Case 3: Multiple rounds $ ./guessing_game.sh Welcome to the Number Guessing Game! I'm thinking of a number between 1 and 100. Enter your guess: 30 Congratulations! You guessed it in 1 attempts! Do you want to play again? (yes/no): yes Starting new game... I'm thinking of a number between 1 and 100. Enter your guess: 50 Too low! Try again. Enter your guess: 60 Congratulations! You guessed it in 2 attempts! Do you want to play again? (yes/no): no Thanks for playing! Goodbye!✋A programming challenge can be solved in more than one way. The solution presented here is for reference purposes only. You may have written a different program and it could be correct as well.Solution 1: Basic implementaionThis is a straightforward implementation using nested while loops. The outer loop controls whether the player wants to play again, while the inner loop handles the guessing game logic. Key features: Uses $RANDOM % 100 + 1 to generate numbers between 1-100Input validation with regex pattern matchingSimple counter for tracking attempts#!/bin/bash # Number Guessing Game - Basic Implementation # Main game loop play_again="yes" echo "Welcome to the Number Guessing Game!" while [[ "$play_again" == "yes" ]]; do # Generate random number between 1 and 100 secret_number=$((RANDOM % 100 + 1)) attempts=0 guessed=false echo "I'm thinking of a number between 1 and 100." echo # Game loop for current round while [[ "$guessed" == "false" ]]; do # Read user input echo -n "Enter your guess: " read guess # Validate input - check if it's a number if ! [[ "$guess" =~ ^[0-9]+$ ]]; then echo "Invalid input! Please enter a number between 1 and 100." continue fi # Check if guess is in valid range if [[ $guess -lt 1 || $guess -gt 100 ]]; then echo "Your guess must be between 1 and 100!" continue fi # Increment attempt counter ((attempts++)) # Check the guess if [[ $guess -eq $secret_number ]]; then echo "Congratulations! You guessed it in $attempts attempts!" guessed=true elif [[ $guess -lt $secret_number ]]; then echo "Too low! Try again." else echo "Too high! Try again." fi done # Ask if player wants to play again echo echo -n "Do you want to play again? (yes/no): " read play_again play_again=$(echo "$play_again" | tr '[:upper:]' '[:lower:]') if [[ "$play_again" == "yes" ]]; then echo echo "Starting new game..." fi done echo "Thanks for playing! Goodbye!"Solution 2: Using functionsIn this solution, I break down the game into modular functions, making the code more organized and reusable: generate_random(): Generates the secret numbervalidate_input(): Handles all input validationplay_round(): Contains the core game logicask_replay(): Manages the replay promptmain(): Orchestrates the overall game flow#!/bin/bash # Number Guessing Game - Function-based Implementation # Function to generate random number generate_random() { echo $((RANDOM % 100 + 1)) } # Function to validate input validate_input() { local input=$1 # Check if input is a number if ! [[ "$input" =~ ^[0-9]+$ ]]; then echo "Invalid input! Please enter a number between 1 and 100." return 1 fi # Check if number is in range if [[ $input -lt 1 || $input -gt 100 ]]; then echo "Your guess must be between 1 and 100!" return 1 fi return 0 } # Function to play one round play_round() { local secret_number=$(generate_random) local attempts=0 local guess echo "I'm thinking of a number between 1 and 100." echo while true; do # Get user input echo -n "Enter your guess: " read guess # Validate input if ! validate_input "$guess"; then continue fi # Increment attempts ((attempts++)) # Check guess if [[ $guess -eq $secret_number ]]; then echo "Congratulations! You guessed it in $attempts attempts!" break elif [[ $guess -lt $secret_number ]]; then echo "Too low! Try again." else echo "Too high! Try again." fi done } # Function to ask for replay ask_replay() { local response echo echo -n "Do you want to play again? (yes/no): " read response response=$(echo "$response" | tr '[:upper:]' '[:lower:]') [[ "$response" == "yes" ]] } # Main program main() { echo "Welcome to the Number Guessing Game!" while true; do play_round if ! ask_replay; then break fi echo echo "Starting new game..." done echo "Thanks for playing! Goodbye!" } # Run the main program mainSolution 3: Enhanced version with difficulty levelsI added a few extra features: Difficulty levels with different number rangesPerformance feedback based on attemptsHints when guesses are very far offBetter user experience with clear menu options#!/bin/bash # Number Guessing Game - Enhanced Version with Difficulty Levels # Function to display menu show_menu() { echo "Select difficulty level:" echo "1. Easy (1-50)" echo "2. Medium (1-100)" echo "3. Hard (1-200)" echo -n "Enter your choice (1-3): " } # Function to get range based on difficulty get_range() { case $1 in 1) echo 50 ;; 2) echo 100 ;; 3) echo 200 ;; *) echo 100 ;; # Default to medium esac } # Main game echo "Welcome to the Number Guessing Game!" echo play_again="yes" while [[ "$play_again" == "yes" ]]; do # Select difficulty show_menu read difficulty # Validate difficulty selection if ! [[ "$difficulty" =~ ^[1-3]$ ]]; then echo "Invalid choice! Using medium difficulty." difficulty=2 fi # Get range for selected difficulty max_number=$(get_range $difficulty) # Generate random number secret_number=$((RANDOM % max_number + 1)) attempts=0 echo echo "I'm thinking of a number between 1 and $max_number." echo # Game loop while true; do echo -n "Enter your guess: " read guess # Validate input if ! [[ "$guess" =~ ^[0-9]+$ ]]; then echo "Invalid input! Please enter a number." continue fi if [[ $guess -lt 1 || $guess -gt $max_number ]]; then echo "Your guess must be between 1 and $max_number!" continue fi ((attempts++)) # Check guess if [[ $guess -eq $secret_number ]]; then echo "Congratulations! You guessed it in $attempts attempts!" # Give performance feedback if [[ $attempts -le 5 ]]; then echo "Excellent! You're a mind reader!" elif [[ $attempts -le 10 ]]; then echo "Good job! That was quick!" else echo "Well done! Practice makes perfect!" fi break elif [[ $guess -lt $secret_number ]]; then echo "Too low! Try again." # Give hint for very far guesses if [[ $((secret_number - guess)) -gt $((max_number / 4)) ]]; then echo "(Hint: You're quite far off!)" fi else echo "Too high! Try again." # Give hint for very far guesses if [[ $((guess - secret_number)) -gt $((max_number / 4)) ]]; then echo "(Hint: You're quite far off!)" fi fi done # Ask for replay echo echo -n "Do you want to play again? (yes/no): " read play_again play_again=$(echo "$play_again" | tr '[:upper:]' '[:lower:]') if [[ "$play_again" == "yes" ]]; then echo echo "Starting new game..." echo fi done echo "Thanks for playing! Goodbye!"📖 Concepts to reviseThe solutions discussed here use some terms, commands and concepts and if you are not familiar with them, you should learn more about them. Variables: secret_number, attempts, guessArithmetic operations: $RANDOM % 100 + 1, numeric comparisonsConditional statements: if/elif/else for guess validation and checkingLoops: while loops, nested loops, continue statementRegular expressions: [[ "$guess" =~ ^[0-9]+$ ]] for number validationFunctions: Modular code organization (Solutions 2 & 3)Input/Output: read command, echo with -n flagString manipulation: tr command for case conversionCommand substitution: $(command) syntax📚 Further readingIf you are new to bash scripting, we have a streamlined tutorial series on Bash that you can use to learn it from scratch or use it to brush up the basics of bash shell scripting. Bash Scripting Tutorial Series for Beginners [Free]Get started with Bash Shell script learning with practical examples. Also test your learning with practice exercises.Linux HandbookAbhishek Prakash
  12. by: Adnan Shabbir Sat, 31 May 2025 12:15:51 +0000 Tails is a Tor-based project inspired by the Debian Linux distro. Tails works on Tor Foundation, i.e., the onion router. It is supposed to be a secure OS and difficult to trace with ordinary tools/tricks. Tails is used to perform privacy-focused tasks without leaving digital traces. These tasks include accessing or monitoring the target, i.e., it is recommended to access the identity type of data ethically (with consent of the target). Today, this guide brings a brief walkthrough of the Tails OS and also lists the process to set up Tails. Tails OS | A Quick Walkthrough Tails Development and Merger With Tor Release Cycle Top Features of Tails OS Built-in Security and Privacy Tools for Maximum Anonymity Persistent Vs Non-Persistent Storage in Tails How to Install and Set up Tails on a USB Drive (Step-by-Step Guide) Hardware Requirements for Installing Tails Step 1: Download and Verify the Tails OS Disk Image (For USB or Virtual Machines) Step 2: Install Tails Should You Use Tails? | Technical Pros and Cons Conclusion Tails OS | A Quick Walkthrough Let’s have a quick walkthrough of the features, some facts, and tools that Tails has: Tails Development and Merger With Tor Tails was first released in 2009 as an iteration of Incognito, a Gentoo-based Linux distribution. The Tails project was originally named “Amnesia,” and now “Amnesia” is the default username/hostname of the Tails OS. In 2023, the Tails submitted a request to merge with Tor, which was completed in 2024, and now Tails is a Tor project. Release Cycle Tails usually release the update after every 6-8 weeks. However, the major release (Like 5.0, 6.0, 7.0) is expected approximately every 2 years. Top Features of Tails OS Communication via Tails is done using Tor (The Onion Router). Direct or non-Tor traffic is blocked by default. Can create persistent (keeping the data) and non-persistent (temporary) storage. Tails verifies and authenticates the Tails version you acquire. Wipes out the memory (RAM) after every reboot or shutdown, nullifying the chance of accessing the sensitive data, i.e., passwords, logins, etc, after restarts/ shutdowns. MAC Address Spoofing Built-in Security and Privacy Tools for Maximum Anonymity Tor Network: An Anonymous network to route traffic anonymously. Thunderbird: An email client to send/receive encrypted emails. KeePassXc: A password manager to securely save passwords. Electrum: Bitcoin wallet OnionShare: Sharing files/media anonymously MAT2: A tool to remove metadata from files, i.e., PDF. GnuPG (GPG): Tool for encrypting, signing, and verifying emails, using Public-Key cryptography. Persistent Vs Non-Persistent Storage in Tails Before proceeding to its setup, let‘s have a look at the difference between Persistent and Non-Persistent. Feature Persistent Non-Persistent Data Saving Yes No Boot Time Slight Longer Faster than Non-persistent Recommended For When you want to have the data in the upcoming sessions. Maximum Anonymity How to Install and Set up Tails on a USB Drive (Step-by-Step Guide) Why are you installing Tails? If the purpose is anonymity, you need to create a non-persistent Live USB. However, if the purpose is to learn and implement, then you can create a persistent one to keep the history and some data from the previous sessions. Recommended: Use Tails as a Live OS, i.e., a non-persistent OS. Not Recommended: Avoid installing it on your primary host or primary virtual machine, where traces can persist. Hardware Requirements for Installing Tails 64-bit processor Minimum 2GB RAM (Recommended is 4GB) Minimum 8 GB USB drive (Recommended is 16GB) Step 1: Download and Verify the Tails OS Disk Image (For USB or Virtual Machines) Download the Tails (either for USB sticks or the ISO file for Virtual machines). Download Tails: Once downloaded, verify your downloaded version: Confirm that the verification is successful before proceeding further: Step 2: Install Tails Once done, you must have a USB bootable tool like balenaEtcher (if using Linux), Rufus (if using Windows), etc. Here, I have listed two possibilities: Installation Option 1: Installing Tails Using the GNOME Disks App Installation Option 2: Installing Tails Using the Balena Etcher   Installation Option 1: GNOME Disks App If you are using a GNOME desktop environment, you can make the Tails USB using the GNOME Disks Desktop application. Here’s the process. Attach the USB with the Linux OS, and open the “GNOME Disks” app. Now, select the USB and click the “vertical ellipsis”. It will then ask you to choose the Disk Image: Confirm to start writing Tails on USB: This will take a few minutes. Once all done, you can eject the drive and boot from the USB to run Tails in an isolated environment. Installation Option 2: Installing Tails Using the balenaEtcher First, you must download and install the Balena Etcher on your respective Linux distribution. Once installed, you have to make the USB bootable with the Tails disk image that you have already downloaded. Follow this guide to briefly understand how to install and use Balena Etcher Setting Up Persistent Storage and Administrator Password When you boot from Tails, you will have to pass through the following interface, where you can create persistent storage and set the administrator password. Persistent Storage: To keep the data, history for further sessions. Administrator Password: To handle the permissions or admin password required for installing applications. Now, you have to set the Tor connection, where you have two options, i.e., choose “Connect to Tor automatically”. This way, you can set anonymity through Tails. What is Tor/Onion Circuits: The Path that the Tor network uses to route traffic from a user’s device to the destination server with anonymity. Here’s the terminal look of the Tails: Here you go with the Tails: Should You Use Tails? | Technical Pros and Cons If you still have questions about whether Tails is a perfect fit for me or not, don’t worry, I have compiled a technical Pros/Cons of Tails to assist you in this regard: Technical Feature/Component Pros Cons Tor-based Anonymity Routes traffic through the Tor network by default. Some websites discourage the Tor Project. Data Security It’s RAM-dependent, and thus, data is wiped out after every boot, i.e., no data breach or tracing through data Data is lost, i.e., the new Tails user who is not familiar with non-persistent working. Once the user is familiar with the system, this issue will decrease. Privacy Tools Built-in tools for file sharing, password, email client, etc. Limited application availability (outside the default installation) No Installation Just plug and play. Plug in the live USB of Tails, and you are good to go. No hard and time-consuming installations. Unstable performance compared to the full-fledged installed system. Hardware Protection Tails spoofs MAC addresses. So, nothing beyond that when it comes to security. It may malfunction sometimes, i.e., in a conflict with the internet hardware devices. Disk Image Verification Disk Image is briefly verified on the Tails official website. It might be difficult for the new or non-technical users. System Footprint A very small footprint, i.e., negligible, because of the advanced encryption/protection level. This makes it not suitable for routine or daily tasks. Updates Frequent Updates,i.e., every 6 weeks. Create a bootable system with every update. Pro-Tip: For maximum security, always use the non-persistent USB for Tails and enjoy this state-of-the-art tool in the tech era. Conclusion Tails OS is one of the best anonymity tools based on the Debian distro and is a part of the Tor project. With one end in Open Source (Linux-based) and the other in anonymity (Tor project). Tails OS is installed and used as a Live non-persistent USB, which minimizes the risk of any traces. Today, I have drafted an in-depth review of the Tails OS, including its installation on a USB as well. FAQs: Q1: Is Tails OS Legal? Yes, Tails is legal. Tails is an open-source Debian-inspired Tor project. The Onion Routing (Tor) nature of Tails makes it suspicious but not illegal. Q2: Does Tails hide your IP? Tails is a Tor project, and when routing, it hides your IP and server information. Q3: Does Tails run in RAM? Since it’s an amnestic, no data or history is kept. This anonymity is due to RAM. It temporarily stores data and refreshes it after each session. Q4: What is the Tails filesystem? Tails works on the Ext4 file system, i.e., Fourth Extended Filesystem.
  13. by: Abhishek Kumar Sat, 31 May 2025 04:29:37 GMT In one of my earlier articles, I showed how you can preview HTML files inside Visual Studio Code. That setup worked well for testing static pages, but what if you want to go beyond markup and bring interactivity into the mix? With JavaScript being the backbone of the modern web and countless developers now diving into frameworks like React, Vue, and Svelte, being able to run JavaScript code directly inside VS Code becomes almost essential. Running JavaScript in the editor helps you avoid constant context-switching, reduces distractions, and gives you immediate feedback when debugging. There are two approaches here: Running JavaScript inside VS Code using Node.js: most efficient and editor-native approach. Run it in a browser or using extensions: handy for quick tests or visual feedback.Let's see about using them. Understanding the role of Node.jsJavaScript was originally designed to run inside browsers, which come with their own JavaScript engines (like V8 in Chrome). Node.js takes that same V8 engine and brings it to your local machine. This lets you run JavaScript outside the browser, directly from the command line or terminal. It’s particularly useful for backend work, automation scripts, or just quick testing without the overhead of an HTML shell. If you're unsure whether Node.js is already installed on your system, open a terminal and type: node -vIf you see a version number, you’re all set. If not, you’ll need to download Node.js and follow the installation instructions for your operating system. We have covered node installation on Ubuntu. Install Node.js and npm on Ubuntu Linux [Free Cheat Sheet]Node.js and npm can be easily installed using the Ubuntu repository or the NodeSource repository. Learn both ways of installing Node.js on Ubuntu Linux.It's FOSSAbhishek PrakashSet up a JavaScript projectOnce everything’s installed, open VS Code and create a new folder for your project. Inside it, launch the terminal (Ctrl + ~ or Terminal > New Terminal) and run npm init -y. This initializes a basic project and creates a package.json file, which will be useful for managing your scripts and dependencies later. With the environment ready, create a new file named app.js and add a bit of JavaScript, for example: console.log("Hello, VS Code!"); To run it, simply type node app.js in the terminal. The output will appear immediately in the console, confirming that Node is executing your file properly. Add a custom script for simpler runsTo make things smoother, especially as your project grows, it’s a good idea to define a custom script in your package.json file. Open that file and find the "scripts" section, then add: "start": "node app.js" This allows you to run your script just by typing npm start, instead of repeating the filename every time. Optional: Using the Code Runner extensionIf you prefer a quick way to execute small snippets without setting up a project, Code Runner can help. It’s a lightweight VS Code extension that runs code in a sandboxed output window. To get started: Open the Extensions tab in VS Code.Search for “Code Runner” and install it.Open a .js file, write some code, right-click, and select “Run Code.”For example, a file like example.js with: console.log("Hello from Code Runner!");It will output directly to VS Code’s "Output" tab. The main limitation here is that it doesn’t use the integrated terminal like we used above, which can restrict input/output behavior for more complex scripts. Wrapping upWith Node.js set up inside VS Code, running JavaScript becomes a seamless part of your workflow, no browser tabs or external tools required. Whether you're testing a quick function or building out a larger project, using the terminal and custom npm scripts keeps things fast and distraction-free. Extensions like Code Runner can help for quick one-off tests, but for anything serious, sticking to the Node-powered method inside VS Code gives you more control, better error output, and a real development feel. Once this setup becomes second nature, jumping into frameworks like React or Express will feel a lot more natural too. Now that you’ve got the tools, go ahead, experiment, break stuff, debug, and build.
  14. by: Temani Afif Fri, 30 May 2025 13:45:43 +0000 Ready for the second part? We are still exploring the shape() function, and more precisely, the arc command. I hope you took the time to digest the first part because we will jump straight into creating more shapes! As a reminder, the shape() function is only supported in Chrome 137+ and Safari 18.4+ as I’m writing this in May 2025. Sector shape Another classic shape that can also be used in pie-like charts. It’s already clear that we have one arc. As for the points, we have two points that don’t move and one that moves depending on how much the sector is filled. The code will look like this: .sector { --v: 35; /* [0 100]*/ aspect-ratio: 1; clip-path: shape(from top, arc to X Y of R, line to center); } We define a variable that will control the filling of the sector. It has a value between 0 and 100. To draw the shape, we start from the top, create an arc until the point (X, Y), and then we move to the center. Yes! Unlike the polygon() function, we have keywords for the particular cases such as top, bottom, left, etc. It’s exactly like background-position that way. I don’t think I need to detail this part as it’s trivial, but it’s good to know because it can make your shape a bit easier to read. The radius of the arc should be equal to 50%. We are working with a square element and the sector, which is a portion of a circle, need to fill the whole element so the radius is equal to half the width (or height).1 As for the point, it’s placed within that circle, and its position depends on the V value. You don’t want a boring math explanation, right? No need for it, here is the formula of X and Y: X = 50% + 50% * sin(V * 3.6deg) Y = 50% - 50% * cos(V * 3.6deg) Our code becomes: .sector { --v: 35; /* [0 100] */ aspect-ratio: 1; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--v) * 3.6deg)) calc(50% - 50% * cos(var(--v) * 3.6deg)) of 50%, line to center); } CodePen Embed Fallback Hmm, the result is not good, but there are no mistakes in the code. Can you figure out what we are missing? It’s the size and direction of the arc! Remember what I told you in the last article? You will always have trouble with them, but if we try the different combinations, we can easily fix the issue. In our case, we need to use: small cw. CodePen Embed Fallback Better! Let’s try it with more values and see how the shape behaves: CodePen Embed Fallback Oops, some values are good, but others not so much. The direction needs to be clockwise, but maybe we should use large instead of small? Let’s try: CodePen Embed Fallback Still not working. The issue here is that we are moving one point of the arc based on the V value, and this movement creates a different configuration for the arc command. Here is an interactive demo to better visualize what is happening: CodePen Embed Fallback When you update the value, notice how large cw always tries to follow the largest arc between the points, while small cw tries to follow the smallest one. When the value is smaller than 50, small cw gives us a good result. But when it’s bigger than 50, the large cw combination is the good one. I know, it’s a bit tricky and I wanted to study this particular example to emphasize the fact that we can have a lot of headaches working with arcs. But the more issues we face, the better we get at fixing them. The solution in this case is pretty simple. We keep the use of large cw and add a border-radius to the element. If you check the previous demo, you will notice that even if large cw is not producing a good result, it’s filling the area we want. All we need to do is clip the extra space and a simple border-radius: 50% will do the job! CodePen Embed Fallback I am keeping the box-shadow in there so we can see the arc, but we can clearly see how border-radius is making a difference on the main shape. There is still one edge case we need to consider. When the value is equal to 100, both points of the arc will have the same coordinates, which is logical since the sector is full and we have a circle. But when it’s the case, the arc will do nothing by definition and we won’t get a full circle. To fix this, we can limit the value to, for example, 99.99 to avoid reaching 100. It’s kind of hacky, but it does the job. .sector { --v: 35; /* [0 100]*/ --_v: min(99.99, var(--v)); aspect-ratio: 1; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% large cw, line to center); border-radius: 50%; } Now our shape is perfect! And don’t forget that you can apply it to image elements: CodePen Embed Fallback Arc shape Similar to the sector shape, we can also create an arc shape. After all, we are working with the arc command, so we have to do it. We already have half the code since it’s basically a sector shape without the inner part. We simply need to add more commands to cut the inner part. .arc { --v: 35; --b: 30px; --_v: min(99.99, var(--v)); aspect-ratio: 1; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw large, line to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)), arc to 50% var(--b) of calc(50% - var(--b)) large ); border-radius: 50%; } From the sector shape, we remove the line to center piece and replace it with another line command that moves to a point placed on the inner circle. If you compare its coordinates with the previous point, you will see an offset equal to --b, which is a variable that defines the arc’s thickness. Then we draw an arc in the opposite direction (ccw) until the point 50% var(--b), which is also a point with an offset equal to --b from the top. I am not defining the direction of the second arc since, by default, the browser will use ccw. CodePen Embed Fallback Ah, the same issue we hit with the sector shape is striking again! Not all the values are giving a good result due to the same logic we saw earlier, and, as you can see, border-radius is not fixing it. This time, we need to find a way to conditionally change the size of the arc based on the value. It should be large when V is bigger than 50, and small otherwise. Conditions in CSS? Yes, it’s possible! First, let’s convert the V value like this: --_f: round(down, var(--_v), 50) The value is within the range [0 99.99] (don’t forget that we don’t want to reach the value 100). We use round() to make sure it’s always equal to a multiple of a specific value, which is 50 in our case. If the value is smaller than 50, the result is 0, otherwise it’s 50. There are only two possible values, so we can easily add a condition. If --_f is equal to 0 we use small; otherwise, we use large: .arc { --v: 35; --b: 30px; --_v: min(99.99, var(--v)); --_f: round(down,var(--_v), 50); --_c: if(style(--_f: 0): small; else: large); clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw var(--_c), line to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)), arc to 50% var(--b) of calc(50% - var(--b)) var(--_c) ); } I know what you are thinking, but let me tell you that the above code is valid. You probably don’t know it yet, but CSS has recently introduced inline conditionals using an if() syntax. It’s still early to play with it, but we have found a perfect use case for it. Here is a demo that you can test using Chrome Canary: CodePen Embed Fallback Another way to express conditions is to rely on style queries that have better support: .arc { --v: 35; --b: 30px; --_v: min(99.99, var(--v)); --_f: round(down, var(--_v), 50); aspect-ratio: 1; container-name: arc; } .arc:before { content: ""; clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw var(--_c, large), line to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)), arc to 50% var(--b) of calc(50% - var(--b)) var(--_c, large) ); @container style(--_f: 0) { --_c: small } } The logic is the same but, this feature requires a parent-child relation, which is why I am using a pseudo-element. By default, the size will be large, and if the value of --_f is equal to 0, we switch to small. CodePen Embed Fallback Note that we have to register the variable --_f using @property to be able to either use the if() function or style queries. Did you notice another subtle change I have made to the shape? I removed border-radius and I applied the conditional logic to the first arc. Both have the same issue, but border-radius can fix only one of them while the conditional logic can fix both, so we can optimize the code a little. Arc shape with rounded edges What about adding rounded edges to our arc? It’s better, right? Can you see how it’s done? Take it as a small exercise and update the code from the previous examples to add those rounded edges. I hope you are able to find it by yourself because the changes are pretty straightforward — we update one line command with an arc command and we add another arc command at the end. clip-path: shape(from top, arc to calc(50% + 50% * sin(var(--_v) * 3.6deg)) calc(50% - 50% * cos(var(--_v) * 3.6deg)) of 50% cw var(--_c, large), arc to calc(50% + (50% - var(--b)) * sin(var(--_v) * 3.6deg)) calc(50% - (50% - var(--b)) * cos(var(--_v) * 3.6deg)) of 1% cw, arc to 50% var(--b) of calc(50% - var(--b)) var(--_c, large), arc to top of 1% cw ); If you do not understand the changes, get out a pen and paper, then draw the shape to better see the four arcs we are drawing. Previously, we had two arcs and two lines, but now we are working with arcs instead of lines. And did you remember the trick of using a 1% value for the radius? The new arcs are half circles, so we can rely on that trick where you specify a tiny radius and the browser will do the job for you and find the correct value! CodePen Embed Fallback Conclusion We are done — enough about the arc command! I had to write two articles that focus on this command because it’s the trickiest one, but I hope it’s now clear how to use it and how to handle the direction and size thing, as that is probably the source of most headaches. By the way, I have only studied the case of circular arcs because, in reality, we can specify two radii and draw elliptical ones, which is even more complex. Unless you want to become a shape() master, you will rarely need elliptical arcs, so don’t bother yourself with them. Until the next article, I wrote an article for Frontend Masters where you can create more fancy shapes using the arc command that is a good follow-up to this one. Footnotes (1) The arc command is defined to draw elliptical arcs by taking two radii, but if we define one radius value, it means that the vertical and horizontal radius will use that same value and we have circular arcs. When it’s a length, it’s trivial, but when we use percentages, the value will resolve against the direction-agnostic size, which is equal to the length of the diagonal of the box, divided by sqrt(2). In our case, we have a square element so 50% of the direction-agnostic size will be equal to 50% of sqrt(Width² + Height²)/sqrt(2). And since both width and height are equal, we end with 50% of the width (or the height). ⮑ Better CSS Shapes Using shape() — Part 2: More on Arcs originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
  15. by: Abhishek Prakash Fri, 30 May 2025 17:30:45 +0530 An interesting development came from Microsoft as it released a new terminal-based editor with open source license. I kind of liked it at first glance until I tried my hands on a shell script written in this editor and then I ran into: The issue is that it added the classic Windows-style line endings, which is not liked by UNIX-like systems. I knew it was too good to be true to have something perfect for Linux from Microsoft 🤦 Here are the highlights of this edition : Open-source notification Inbox infrastructureListmonk newsletterHistorical view of system resource utilizationBang bang... shebangAnd memes, news and tools to discover🚀 Level up your coding skills and build your own botsHarness the power of machine learning to create digital agents and more with hot courses like Learning LangChain, The Developer's Playbook for Large Language Model Security, Designing Large Language Model Applications, and more. Part of the purchase goes to Code for America! Check out the ebook bundle here. Humble Tech Book Bundle: Machine Learning, AI, and Bots by O’Reilly 2025Master machine learning with this comprehensive library of coding and programming courses from the pros at O’Reilly.Humble Bundle       This post is for subscribers only Subscribe now Already have an account? Sign in

Important Information

Terms of Use Privacy Policy Guidelines We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.